import pandas as pd
from datetime import datetime
from pvlib.bifacial.pvfactors import pvfactors_timeseries
from tests.conftest import requires_pvfactors, assert_series_equal
import pytest


@pytest.fixture
def example_values():
    """
    Example values from the pvfactors github repo README file:
    https://github.com/SunPower/pvfactors/blob/master/README.rst#quick-start
    """
    inputs = dict(
        timestamps=pd.DatetimeIndex([datetime(2017, 8, 31, 11),
                                     datetime(2017, 8, 31, 12)]),
        solar_zenith=[20., 10.],
        solar_azimuth=[110., 140.],
        surface_tilt=[10., 0.],
        surface_azimuth=[90., 90.],
        axis_azimuth=0.,
        dni=[1000., 300.],
        dhi=[50., 500.],
        gcr=0.4,
        pvrow_height=1.75,
        pvrow_width=2.44,
        albedo=0.2,
        n_pvrows=3,
        index_observed_pvrow=1,
        rho_front_pvrow=0.03,
        rho_back_pvrow=0.05,
        horizon_band_angle=15.,
    )
    outputs = dict(
        expected_ipoa_front=pd.Series([1034.95474708997, 795.4423259036623],
                                      index=inputs['timestamps'],
                                      name=('total_inc_front')),
        expected_ipoa_back=pd.Series([92.12563846416197, 78.05831585685098],
                                     index=inputs['timestamps'],
                                     name=('total_inc_back')),
    )
    return inputs, outputs


@requires_pvfactors
def test_pvfactors_timeseries_list(example_values):
    """Test basic pvfactors functionality with list inputs"""
    inputs, outputs = example_values
    ipoa_inc_front, ipoa_inc_back, _, _ = pvfactors_timeseries(**inputs)
    assert_series_equal(ipoa_inc_front, outputs['expected_ipoa_front'])
    assert_series_equal(ipoa_inc_back, outputs['expected_ipoa_back'])


@requires_pvfactors
def test_pvfactors_timeseries_pandas(example_values):
    """Test basic pvfactors functionality with Series inputs"""

    inputs, outputs = example_values
    for key in ['solar_zenith', 'solar_azimuth', 'surface_tilt',
                'surface_azimuth', 'dni', 'dhi']:
        inputs[key] = pd.Series(inputs[key], index=inputs['timestamps'])

    ipoa_inc_front, ipoa_inc_back, _, _ = pvfactors_timeseries(**inputs)
    assert_series_equal(ipoa_inc_front, outputs['expected_ipoa_front'])
    assert_series_equal(ipoa_inc_back, outputs['expected_ipoa_back'])


@requires_pvfactors
def test_pvfactors_scalar_orientation(example_values):
    """test that surface_tilt and surface_azimuth inputs can be scalars"""
    # GH 1127, GH 1332
    inputs, outputs = example_values
    inputs['surface_tilt'] = 10.
    inputs['surface_azimuth'] = 90.
    # the second tilt is supposed to be zero, so we need to
    # update the expected irradiances too:
    outputs['expected_ipoa_front'].iloc[1] = 800.6524022701132
    outputs['expected_ipoa_back'].iloc[1] = 81.72135884745822

    ipoa_inc_front, ipoa_inc_back, _, _ = pvfactors_timeseries(**inputs)
    assert_series_equal(ipoa_inc_front, outputs['expected_ipoa_front'])
    assert_series_equal(ipoa_inc_back, outputs['expected_ipoa_back'])
